package net.pws.oos.web.mobile;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletContext;

import net.pws.common.beanutils.BeanUtils;
import net.pws.common.jackson.JsonUtils;
import net.pws.common.persistence.EntityManager;
import net.pws.common.util.StringUtils;
import net.pws.oos.biz.BizException;
import net.pws.oos.biz.model.Attachment;
import net.pws.oos.biz.model.Locatable;
import net.pws.oos.biz.model.PhotoMarker;
import net.pws.oos.biz.query.AttachmentFinder;
import net.pws.oos.biz.service.AttachmentService;
import net.pws.oos.biz.service.storage.FileStorage;
import net.pws.oos.biz.service.storage.PhotoMarkerStorage;
import net.pws.oos.web.dto.AttachmentDto;
import net.pws.oos.web.dto.PhotoMarkerDto;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.multipart.MultipartFile;

@SuppressWarnings("rawtypes")
public abstract class AbstractAttachementAction implements ServletContextAware {
    
    public final transient Log logger = LogFactory.getLog(AbstractAttachementAction.class);

    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
            "yyyyMM");

    @Autowired
    @Qualifier("attachmentPath")
    private String attachmentPath;

    @Autowired
    protected AttachmentService attachmentService;
    
    @Autowired
    protected AttachmentFinder attachmentFinder;
    
    @Autowired
    protected EntityManager entityManager;
    
    private ServletContext context;

    public void setServletContext(ServletContext context) {
        this.context = context;
    }

    /**
     * 为URL加上前面的路径，不包括域名、端口及应用上下文
     * 
     * @param att
     */
    protected void filterUri(AttachmentDto att) {
        if (att == null) {
            return;
        }
        String orgiUri = att.getOrgiUri();
        if (StringUtils.isNotBlank(orgiUri)) {
            StringBuilder sb = new StringBuilder(Attachment.ATTACHMENT_ROOT);
            sb.append("/").append(orgiUri);
            att.setOrgiUri(sb.toString());
        }
        String mediumUri = att.getMediumUri();
        if (StringUtils.isNotBlank(mediumUri)) {
            StringBuilder sb = new StringBuilder(Attachment.ATTACHMENT_ROOT);
            sb.append("/").append(mediumUri);
            att.setMediumUri(sb.toString());
        }
        String smallUri = att.getSmallUri();
        if (StringUtils.isNotBlank(smallUri)) {
            StringBuilder sb = new StringBuilder(Attachment.ATTACHMENT_ROOT);
            sb.append("/").append(smallUri);
            att.setSmallUri(sb.toString());
        }
    }

    protected Attachment storeAttachment(AttachmentDto dto, Locatable locatable) {
        MultipartFile file = dto.getFile();

        // 照片标记
        List<PhotoMarker> markers = getMarkers(dto.getJson());

        // 保存附件到文件系统
        String orginRelative = null;
        String largeRelative = null;
        String smallRelative = null;
        String mediumRelative = null;
        FileStorage storage = null;
        if (Attachment.PHOTO_TYPE.equals(dto.getType())) {
            // String ext = IoUtil.getExtendName(file.getOriginalFilename());

            // 图片相对路径
            StringBuilder folder = new StringBuilder(getMonthFolder());
            folder.append("/").append(dto.getResourceId()).append("/");
            String fileName = UUID.randomUUID().toString();
            orginRelative = new StringBuilder().append(folder).append(fileName)
                    .append("_o").append(PhotoMarkerStorage.DEFAULT_EXT_NAME)
                    .toString();
            largeRelative = new StringBuilder().append(folder).append(fileName)
                    .append(PhotoMarkerStorage.DEFAULT_EXT_NAME).toString();
            mediumRelative = new StringBuilder().append(folder)
                    .append(fileName).append("_m")
                    .append(PhotoMarkerStorage.DEFAULT_EXT_NAME).toString();
            smallRelative = new StringBuilder().append(folder).append(fileName)
                    .append("_s").append(PhotoMarkerStorage.DEFAULT_EXT_NAME)
                    .toString();

            // 图片存储绝对路径
            String orginPath = getAttachmentRoot() + "/" + orginRelative;
            String largePath = getAttachmentRoot() + "/" + largeRelative;
            String mediumPath = getAttachmentRoot() + "/" + mediumRelative;
            String smallPath = getAttachmentRoot() + "/" + smallRelative;
            storage = new PhotoMarkerStorage(file, orginPath, largePath,
                    mediumPath, smallPath, markers, dto, locatable);
        } else if (Attachment.VIDEO_TYPE.equals(dto.getType())) {

        } else {

        }
        if (storage == null) {
            throw new BizException("未保存文件！");
        }

        try {
            storage.store();
        } catch (Exception e) {
            throw new BizException("未保存文件！", e);
        }

        // 保存附件到数据库
        Attachment attachment = new Attachment();
        BeanUtils.copyProperties(attachment, dto);
        attachment.setUploadDate(new Date());
        attachment.setOrgiUri(largeRelative);
        attachment.setMediumUri(mediumRelative);
        attachment.setSmallUri(smallRelative);
        attachmentService.saveAttachment(attachment, markers);

        return attachment;
    }

    protected List<PhotoMarker> getMarkers(String json) {
        List<PhotoMarker> markers = new ArrayList<PhotoMarker>();
        if (StringUtils.isBlank(json)) {
            return markers;
        }
        List list = JsonUtils.parseList(json);
        if (list == null || list.isEmpty()) {
            return markers;
        }
        for (Object obj : list) {
            PhotoMarker marker = PhotoMarkerDto.to(PhotoMarkerDto.from(obj));
            marker.setId(null);
            markers.add(marker);
        }

        return markers;
    }

    /**
     * 得到文件系统中附件根目录的绝对路径
     * 
     * @return
     */
    private String getAttachmentRoot() {
        if (StringUtils.isBlank(attachmentPath)) {
            attachmentPath = context.getRealPath(Attachment.ATTACHMENT_ROOT);
        }
        return attachmentPath;
    }

    /**
     * 获得以yyyyMM形式的目录名
     * 
     * @return
     */
    private static String getMonthFolder() {
        return DATE_FORMAT.format(new Date());
    }

}
